﻿<?xml version="1.0" encoding="utf-8" ?>

<!--
	RegExpress
	
	Copyright (c) 2010, Daniel McGaughran
	
	Licensed under the Apache Licence, Version 2.0 (the "Licence");
	you may not use this file except in compliance with the Licence.
	You may obtain a copy of the License at
	
		http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the Licence is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the Licence for the specific language governing permissions and
	limitations under the Licence.
	
	-->

<Slides>
	<Slide ID="title" Type="Title" Template="TitlePage">
		<Navigation NextID="xkcd" PrevID="" />
		<Title>Regular Expressions</Title>
		<SubTitle>From Zero to Regex Hero</SubTitle>
	</Slide>

	<Slide ID="xkcd" Type="Image" Template="ImagePage">
		<Navigation NextID="whyRegex" PrevID="title" />
		<Title>Regular Expressions</Title>
		<ImageUri>/Resources/Media/xkcdRegex.png</ImageUri>
		<Caption>http://xkcd.com/208/</Caption>
	</Slide>

	<Slide ID="whyRegex" Type="FixedContent" Template="FixedContent\WhyRegexPage">
		<Navigation NextID="simplestRegex" PrevID="xkcd" />
		<Title>Why Regular Expressions?</Title>
	</Slide>

	<Slide ID="simplestRegex" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="usingInDotNet1" PrevID="whyRegex" />
		<Title>Simplest Regexes</Title>
		<Caption>Similar to String.Contains</Caption>
		<MatchModel>
			<RegExpression>Intergen</RegExpression>
			<MatchCases>
				<MatchCase>Intergen</MatchCase>
				<MatchCase>Interesting</MatchCase>
				<MatchCase>Intergenite</MatchCase>
				<MatchCase>intergen</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>

	<Slide ID="usingInDotNet1" Type="SourceCode" Template="SourceCodePage">
		<Navigation NextID="usingInDotNet2" PrevID="simplestRegex" />
		<Title>Using .NET Regexes in Code</Title>
		<Caption>Declaring a Regex on-the-fly</Caption>
		<SourceCode>
		<![CDATA[class SomeMatcher
{
	public string Expression {get; set;}

	public bool HasMatch(string input)
	{
		return Regex.IsMatch(input, Expression);
	}

	public bool HasCaseInsensitiveMatch(string input)
	{
		return Regex.IsMatch(input, Expression, RegexOptions.IgnoreCase);
	}
}]]>
		</SourceCode>
	</Slide>


	<Slide ID="usingInDotNet2" Type="SourceCode" Template="SourceCodePage">
		<Navigation NextID="alternation" PrevID="usingInDotNet1" />
		<Title>Using .NET Regexes in Code</Title>
		<Caption>Declaring a Regex for reuse</Caption>
		<SourceCode>
			<![CDATA[class SomeMatcher
{
	private const string _expression = "Intergen";
	private static Regex _matcher;

	static SomeMatcher()
	{
		_matcher = new Regex(_expression,
				RegexOptions.Compiled | RegexOptions.CultureInvariant);
	}

	public bool HasMatch(string input)
	{
		return _matcher.IsMatch(input);
	}
}]]>
		</SourceCode>
	</Slide>

	<Slide ID="alternation" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="alternationBTS" PrevID="usingInDotNet2" />
		<Title>Alternation</Title>
		<Caption>Uses '|' as a special character</Caption>
		<MatchModel>
			<RegExpression>doc|rtf|pdf|txt</RegExpression>
			<MatchCases>
				<MatchCase>SomeReport.doc</MatchCase>
				<MatchCase>ScratchPad.rtf</MatchCase>
				<MatchCase>Prospectus.pdf</MatchCase>
				<MatchCase>readme.txt</MatchCase>
				<MatchCase>RunMe.exe</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>

	<Slide ID="alternationBTS" Type="Image" Template="DiagramPage">
		<Navigation NextID="anchorsAZ" PrevID="alternation" />
		<Title>Alternation</Title>
		<Caption>How it works behind-the-scenes</Caption>
		<ImageUri>/Resources/Media/RegexAlternation.png</ImageUri>
	</Slide>

	<Slide ID="anchorsAZ" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="quantStar" PrevID="alternationBTS" />
		<Title>Anchors: '^' and '$'</Title>
		<Caption>Matches positions of start/end</Caption>
		<MatchModel>
			<RegExpression>doc</RegExpression>
			<Options IsCaseIgnored="1" />
			<MatchCases>
				<MatchCase>SomeReport.doc</MatchCase>
				<MatchCase>SomeReport.docx</MatchCase>
				<MatchCase>Document1.xml</MatchCase>
				<MatchCase>Doctor Who</MatchCase>
				<MatchCase>Indoctrinate</MatchCase>
				<MatchCase>OpenMe.doc.exe</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>

	<Slide ID="quantStar" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="quantPlus" PrevID="anchorsAZ" />
		<Title>Quantifiers: '*'</Title>
		<Caption>Matches the previous item 0 or more times</Caption>
		<MatchModel>
			<RegExpression>^OMG!*$</RegExpression>
			<MatchCases>
				<MatchCase>OMG</MatchCase>
				<MatchCase>OMG!</MatchCase>
				<MatchCase>OMG!!</MatchCase>
				<MatchCase>OMG!!!</MatchCase>
				<MatchCase>OMG!OMG!</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>

	<Slide ID="quantPlus" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="quantCustom" PrevID="quantStar" />
		<Title>Quantifiers: '+'</Title>
		<Caption>Matches the previous item 1 or more times</Caption>
		<MatchModel>
			<RegExpression>^Goo+gle$</RegExpression>
			<Options IsCaseIgnored="1" />
			<MatchCases>
				<MatchCase>Gogle</MatchCase>
				<MatchCase>Google</MatchCase>
				<MatchCase>Gooogle</MatchCase>
				<MatchCase>Goooooogle</MatchCase>
				<MatchCase>GooGoogle</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>

	<Slide ID="quantCustom" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="optSpec" PrevID="quantPlus" />
		<Title>Custom Quantifiers</Title>
		<Caption>Matches the previous item as much or as little as specified</Caption>
		<MatchModel>
			<RegExpression>^Go{2,}gle$</RegExpression>
			<Options IsCaseIgnored="1" />
			<MatchCases>
				<MatchCase>Gogle</MatchCase>
				<MatchCase>Google</MatchCase>
				<MatchCase>Gooogle</MatchCase>
				<MatchCase>Goooooogle</MatchCase>
				<MatchCase>GooGoogle</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>

	<Slide ID="optSpec" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="greedyVsLazy" PrevID="quantCustom" />
		<Title>Optional Specifier: '?'</Title>
		<Caption>Matches the previous item 1 or 0 times</Caption>
		<MatchModel>
			<RegExpression>^docx?$</RegExpression>
			<Options IsCaseIgnored="1" />
			<MatchCases>
				<MatchCase>doc</MatchCase>
				<MatchCase>docx</MatchCase>
				<MatchCase>dock</MatchCase>
				<MatchCase>xml</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>


	<Slide ID="greedyVsLazy" Type="FindMatches" Template="FindMatchesPage">
		<Navigation NextID="greedyVsLazy2" PrevID="optSpec" />
		<Title>Greedy v Lazy</Title>
		<Caption>Quantifiers are greedy by default.
		Append '?' to make them lazy.
		</Caption>
		<MatchModel>
			<RegExpression>\d{2,3}</RegExpression>
			<Options IsCaseIgnored="1" />
			<Input>12345</Input>
		</MatchModel>
	</Slide>


	<Slide ID="greedyVsLazy2" Type="FindMatches" Template="FindMatchesPage">
		<Navigation NextID="charClasses" PrevID="greedyVsLazy" />
		<Title>Greedy v Lazy</Title>
		<Caption>Why does it matter?
		</Caption>
		<MatchModel>
			<RegExpression><![CDATA[<.*>]]></RegExpression>
			<Options IsCaseIgnored="1" IsNewlineMatchedByDot="1" />
			<Input>
				<![CDATA[<ul class="bottomLinks horizontalList">
    <li class="first">
        <a href="/Who-We-Are/" title="Who We Are">Who We Are</a>
    </li>
    <li>
        <a href="/What-We-Do/" title="What We Do">What We Do</a>
    </li>
    <li>
        <a href="/Our-Showcase/" title="Our Showcase">Our Showcase</a>
    </li>
    <li>
        <a href="/Our-Events/" title="Our Events">Our Events</a>
    </li>
    <li>
        <a href="/Our-Insight/" title="Our Insight">Our Insight</a>
    </li>
</ul>
]]></Input>
		</MatchModel>
	</Slide>

	<Slide ID="charClasses" Type="FixedContent" Template="FixedContent\CharClassesPage">
		<Navigation NextID="charClasses2" PrevID="greedyVsLazy2" />
		<Title>A Better Idea than Wildcards</Title>
	</Slide>

	<Slide ID="charClasses2" Type="FixedContent" Template="FixedContent\PreBakedCharClassesPage">
		<Navigation NextID="escapeSeq" PrevID="charClasses" />
		<Title>Pre-baked Character Classes</Title>
	</Slide>

	<Slide ID="escapeSeq" Type="FixedContent" Template="FixedContent\EscapeSeqPage">
		<Navigation NextID="escapingInCSharp" PrevID="charClasses2" />
		<Title>Escape Sequences</Title>
	</Slide>


	<Slide ID="escapingInCSharp" Type="SourceCode" Template="SourceCodePage">
		<Navigation NextID="validationApp" PrevID="escapeSeq" />
		<Title>Quoting Expressions in C#</Title>
		<Caption>Tip: Use literal strings to minimise backslashes</Caption>
		<SourceCode>
			<![CDATA[class SomeMatcher
{
	private const string _expression = @"[a-zA-Z]\w*\(""\w+""\);";
	private static Regex _matcher;

	static SomeMatcher()
	{
		_matcher = new Regex(_expression,
				RegexOptions.Compiled | RegexOptions.CultureInvariant);
	}

	public MatchCollection GetMatches(string input)
	{
		return _matcher.Matches(input);
	}
}]]>
		</SourceCode>
	</Slide>


	<Slide ID="validationApp" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="breakItDown2" PrevID="escapingInCSharp" />
		<Title>Application of Regexes: Validation</Title>
		<Caption>Validate email addresses</Caption>
		<MatchModel>
			<RegExpression><![CDATA[^[\w!-]+(\.[\w!-]+)*@[\w!-]+(\.[\w!-]+)+$]]></RegExpression>
			<Options IsCaseIgnored="1" />
			<MatchCases>
				<MatchCase>john.smith@gmail.com</MatchCase>
				<MatchCase>john-smith@gmail.com</MatchCase>
				<MatchCase>jsmith@paradise.net.nz</MatchCase>
				<MatchCase>n/a</MatchCase>
				<MatchCase>a@b</MatchCase>
				<MatchCase>a@b.com</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>

	<Slide ID="breakItDown" Type="Image" Template="DiagramPage">
		<Navigation NextID="breakItDown2" PrevID="validationApp" />
		<Title>Breaking It Down</Title>
		<Caption><![CDATA[^[\w!-]+(\.[\w!-]+)*@[\w!-]+(\.[\w!-]+)+$]]></Caption>
		<ImageUri>/Resources/Media/RegexAlternation.png</ImageUri>
	</Slide>

	<Slide ID="breakItDown2" Type="SourceCode" Template="SourceCodePage">
		<Navigation NextID="groupingSE" PrevID="validationApp" />
		<Title>Breaking It Down in C#</Title>
		<Caption>Tip: Use String.Format to compose master expression</Caption>
		<SourceCode>
			<![CDATA[class EmailValidator
{
	//Breaking down /^[\w!-]+(\.[\w!-]+)*@[\w!-]+(\.[\w!-]+)+$/
	private const string _allowedCharsRun = @"[\w!-]+";
	private const string _validatorTemplate = @"^{0}(\.{0})*@{0}(\.{0})+$";
	private static Regex _emailValidator;

	static EmailValidator()
	{
		string validatorExpression = String.Format(_validatorTemplate, _allowedCharsRun);
		_emailValidator = new Regex(validatorExpression,
				RegexOptions.Compiled | RegexOptions.CultureInvariant);
	}

	public static bool IsEmailAddress(string input)
	{
		return _emailValidator.IsMatch(input);
	}
}]]>
		</SourceCode>
	</Slide>


	<Slide ID="groupingSE" Type="BasicMatch" Template="BasicIsMatchPage">
		<Navigation NextID="groupCaptures" PrevID="breakItDown2" />
		<Title>A Side-effect of Grouping</Title>
		<Caption>Group contents are captured</Caption>
		<MatchModel>
			<RegExpression><![CDATA[^[\w!-]+(\.[\w!-]+)*@[\w!-]+(\.[\w!-]+)+$]]></RegExpression>
			<Input>john.smith@gmail.com</Input>
		</MatchModel>
	</Slide>


	<Slide ID="groupCaptures" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="namedCaptures" PrevID="groupingSE" />
		<Title>Matching Captured Groups</Title>
		<Caption>Use escape sequences \1 to \9</Caption>
		<MatchModel>
			<RegExpression><![CDATA[\b([A-Za-z]+)-\1\b]]></RegExpression>
			<Options IsCaseIgnored="1" />
			<MatchCases>
				<MatchCase>yo-yo</MatchCase>
				<MatchCase>tam-tam</MatchCase>
				<MatchCase>tam-tams</MatchCase>
				<MatchCase>tim-tam</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>


	<Slide ID="namedCaptures" Type="BasicMatch" Template="BasicIsMatchPage">
		<Navigation NextID="matchingNamedCaptures" PrevID="groupCaptures" />
		<Title>Giving Captured Groups a Name</Title>
		<Caption>Group contents are captured</Caption>
		<MatchModel>
			<RegExpression><![CDATA[\\(?<filename>[\w -]+)\.(?<extn>[\w]+)\b]]></RegExpression>
			<Options IsCaseIgnored="1" />
			<Input>C:\Windows\System32\ieframe.dll</Input>
		</MatchModel>
	</Slide>


	<Slide ID="matchingNamedCaptures" Type="MultiMatch" Template="MultiIsMatchPage">
		<Navigation NextID="namedCaptureCaveats" PrevID="namedCaptures" />
		<Title>Matching Named Captured Groups</Title>
		<Caption>Use escape sequences \k&lt;name&gt; or \k'name'</Caption>
		<MatchModel>
			<RegExpression><![CDATA[\b(?<bit>[A-Za-z]+)-\k<bit>\b]]></RegExpression>
			<Options IsCaseIgnored="1" />
			<MatchCases>
				<MatchCase>yo-yo</MatchCase>
				<MatchCase>tam-tam</MatchCase>
				<MatchCase>tam-tams</MatchCase>
				<MatchCase>tim-tam</MatchCase>
			</MatchCases>
		</MatchModel>
	</Slide>


	<Slide ID="namedCaptureCaveats" Type="BasicMatch" Template="BasicIsMatchPage">
		<Navigation NextID="extractionExample" PrevID="matchingNamedCaptures" />
		<Title>Named Captured Groups: Caveats</Title>
		<Caption>Named groups are enumerated after unnamed groups</Caption>
		<MatchModel>
			<RegExpression><![CDATA[\\(?<filename>[\w -]+)\.([\w]+)\b]]></RegExpression>
			<Options IsCaseIgnored="1" />
			<Input>C:\Windows\System32\ieframe.dll</Input>
		</MatchModel>
	</Slide>


	<Slide ID="extractionExample" Type="SourceCode" Template="SourceCodePage">
		<Navigation NextID="lookahead" PrevID="namedCaptureCaveats" />
		<Title>Example: Data Extraction</Title>
		<Caption>Index the Groups collection, retrieve the value</Caption>
		<SourceCode>
			<![CDATA[class UrlExtractor
{
	//Extracting URLs with /<a [^>]*?href="([^"]*)"[^>]*>/
	private const string _urlExtractorExpression = @"<a [^>]*?href=""([^""]*)""[^>]*>";
	private static Regex _urlExtractor;

	static UrlExtractor()
	{
		_urlExtractor = new Regex(_urlExtractorExpression,
				RegexOptions.Compiled | RegexOptions.CultureInvariant);
	}

	public static List<string> GetUrls(string input)
	{
		List<string> urls = new List<string>();
		MatchCollection matches = _urlExtractor.Matches(input);
		
		foreach(Match currentMatch in matches)
		{
			string currentUrl = currentMatch.Groups[1].Value;
			urls.Add(currentUrl);
		}
		
		return urls;
	}
}]]>
		</SourceCode>
	</Slide>

	<Slide ID="lookahead" Type="FindMatches" Template="FindMatchesPage">
		<Navigation NextID="lookaroundExpl" PrevID="extractionExample" />
		<Title>Another Example</Title>
		<Caption>Finding tags without a 'title' attribute</Caption>
		<MatchModel>
			<RegExpression><![CDATA[<[a-zA-Z]\w*[^>]*>]]></RegExpression>
			<Options IsCaseIgnored="1" />
			<Input>
				<![CDATA[<ul class="bottomLinks horizontalList">
    <li class="title">
        <a href="/Who-We-Are/" title="Who We Are">Who We Are</a>
    </li>
    <li>
        <a href="/What-We-Do/" title="What We Do">What We Do</a>
    </li>
    <li>
        <a href="/Our-Showcase/" title="Our Showcase">Our Showcase</a>
    </li>
    <li>
        <a href="/Our-Events/" title="Our Events">Our Events</a>
    </li>
    <li>
        <a href="/Our-Insight/" title="Our Insight">Our Insight</a>
    </li>
</ul>
]]>
			</Input>
		</MatchModel>
	</Slide>

	<Slide ID="lookaroundExpl" Type="FixedContent" Template="FixedContent\LookaroundPage">
		<Navigation NextID="replacementCode" PrevID="lookahead" />
		<Title>Lookahead &amp; Lookbehind</Title>
	</Slide>


	<Slide ID="replacementCode" Type="SourceCode" Template="SourceCodePage">
		<Navigation NextID="replacementExample" PrevID="lookaroundExpl" />
		<Title>Find &amp; Replace</Title>
		<Caption>Use Regex.Replace</Caption>
		<SourceCode>
			<![CDATA[class UrlExtractor
{
	//Extracting URLs with /<a ([^>]*?)href="([^"]*)"([^>]*)>/
	private const string _urlExtractorExpression = @"<a ([^>]*?)href=""([^""]*)""([^>]*)>";
	private static Regex _urlExtractor;

	static UrlExtractor()
	{
		_urlExtractor = new Regex(_urlExtractorExpression,
				RegexOptions.Compiled | RegexOptions.CultureInvariant);
	}

	public static string ReplaceUrls(string input, string replacementExpression)
	{
		string output = _urlExtractor.Replace(input, replacementExpression);
		return output;
	}
}]]>
		</SourceCode>
	</Slide>

	<Slide ID="replacementExample" Type="ReplaceMatches" Template="ReplaceMatchesPage">
		<Navigation NextID="replacementExample2" PrevID="replacementCode" />
		<Title>Replacement Example</Title>
		<Caption>Removing HTML tags</Caption>
		<MatchModel>
			<RegExpression><![CDATA[<a ([^>]*?)href="([^"]*)"([^>]*)>]]></RegExpression>
			<ReplacementExpression><![CDATA[<a $1href="#"$3>]]></ReplacementExpression>
			<Options IsCaseIgnored="1" />
			<Input>
				<![CDATA[<ul class="bottomLinks horizontalList">
    <li class="first">
        <a href="/Who-We-Are/" title="Who We Are">Who We Are</a>
    </li>
    <li>
        <a href="/What-We-Do/" title="What We Do">What We Do</a>
    </li>
    <li>
        <a href="/Our-Showcase/" title="Our Showcase">Our Showcase</a>
    </li>
    <li>
        <a href="/Our-Events/" title="Our Events">Our Events</a>
    </li>
    <li>
        <a href="/Our-Insight/" title="Our Insight">Our Insight</a>
    </li>
</ul>
]]>
			</Input>
		</MatchModel>
	</Slide>

	<Slide ID="replacementExample2" Type="ReplaceMatches" Template="ReplaceMatchesPage">
		<Navigation NextID="ideQuirks1" PrevID="replacementExample" />
		<Title>Replacement Example</Title>
		<Caption>Syntax with named groups</Caption>
		<MatchModel>
			<RegExpression><![CDATA[<a (?<preHref>[^>]*?)href="(?<url>[^"]*)"(?<postHref>[^>]*)>]]></RegExpression>
			<ReplacementExpression><![CDATA[<a ${preHref}href="#"${postHref}>]]></ReplacementExpression>
			<Options IsCaseIgnored="1" />
			<Input>
				<![CDATA[<ul class="bottomLinks horizontalList">
    <li class="first">
        <a href="/Who-We-Are/" title="Who We Are">Who We Are</a>
    </li>
    <li>
        <a href="/What-We-Do/" title="What We Do">What We Do</a>
    </li>
    <li>
        <a href="/Our-Showcase/" title="Our Showcase">Our Showcase</a>
    </li>
    <li>
        <a href="/Our-Events/" title="Our Events">Our Events</a>
    </li>
    <li>
        <a href="/Our-Insight/" title="Our Insight">Our Insight</a>
    </li>
</ul>
]]>
			</Input>
		</MatchModel>
	</Slide>

	<Slide ID="ideQuirks1" Type="FixedContent" Template="FixedContent\IdeQuirks1Page">
		<Navigation NextID="ideQuirks2" PrevID="replacementExample2" />
		<Title>Visual Studio IDE Quirks</Title>
	</Slide>

	<Slide ID="ideQuirks2" Type="FixedContent" Template="FixedContent\IdeQuirks2Page">
		<Navigation NextID="links" PrevID="ideQuirks1" />
		<Title>Visual Studio IDE Quirks</Title>
	</Slide>

	<Slide ID="links" Type="FixedContent" Template="FixedContent\LinksPage">
		<Navigation NextID="" PrevID="ideQuirks2" />
		<Title>Links</Title>
	</Slide>

</Slides>